import copy
import traceback
import yaml

from configs.data import GlobalVariable
from utils.connect_db import PostgresDB
from utils.handle_yaml import write_var
from utils.log_control import INFO,WARNING,ERROR
db = PostgresDB()
variable = GlobalVariable()
print('**************************************',variable)


class AssertUtils:  # 断言工具类

    # 执行数据库语句
    def execute_sql(self, sql):
        # res = list(db(sql)[0].values())
        res = db(sql)[0][0]
        return res

    # 断言方法
    def assert_all_cases(self,valid,res,api_info):
        """
        :param res: 接口的响应结果
        :param assert_way: 断言的方式  equals相等，contains包含，db相等，db_contains
        :param assert_info: 断言信息  [{断言说明信息:[预期结果，实际结果]},{断言说明信息:[预期结果，实际结果]}]
        :return:
        """
        try:
            if valid:  # 如果有断言信息，才需要断言
                for i in valid:
                    for assert_way, assert_info in i.items():
                        # 深拷贝响应信息，防止处理过程中改变原始的响应信息
                        res = copy.deepcopy(res)
                        try:
                            res.json = res.json()
                        except:
                            pass
                        # - 断言状态码200: [200, "status_code"]
                        # - 断言昵称是 文君: ["文君", "${read_extract(昵称nickname)}"]
                        # [{},{}]
                        for i in assert_info:
                            for key, value in i.items():
                                msg = key  # 断言的提示信息
                                yq_result = value[0]
                                try:
                                    sj_result = getattr(res, value[1])
                                except:
                                    sj_result = value[1]
                                INFO.logger.info("-" * 66)
                                # INFO.logger.info(f"断言方式:{assert_way}")
                                # INFO.logger.info(f"断言信息:{msg}")
                                # INFO.logger.info(f"实际结果:{sj_result}")
                                if isinstance(sj_result, dict):  # 如果响应信息的属性值是 字典，需要转成字符串在进行比较
                                    sj_result = yaml.safe_dump(sj_result, allow_unicode=True)
                                else:
                                    sj_result = str(sj_result)
                                if "equals" == assert_way:
                                    assert str(yq_result) == sj_result,f"接口断言失败:{msg}  >> 预期结果：{str(yq_result)} != 实际结果:{str(sj_result)}"
                                    INFO.logger.info(f"{msg}  >> 预期结果：{str(yq_result)}  == 实际结果:{str(sj_result)}")
                                elif "contains" == assert_way:
                                    assert str(yq_result) in sj_result,f"接口断言失败:{msg}  >> 预期结果：{str(yq_result)} not in 实际结果:{str(sj_result)}"
                                    INFO.logger.info(f"{msg}  >> 预期结果：{str(yq_result)}  == 实际结果:{str(sj_result)}")
                                elif "db" in assert_way:
                                    yq_result = self.execute_sql(value[0])
                                    assert str(yq_result) in sj_result,f"接口断言失败:{msg}  >> 预期结果：{str(yq_result)} not in 实际结果:{str(sj_result)}"
                                    INFO.logger.info(f"{msg}  >> 预期结果:{yq_result}，数据库语句: {value[0]}，实际结果:{str(sj_result)}")
                                # else:
                                #     INFO.logger.info(f"预期结果:{yq_result}")
                                else:
                                    assert False,"断言方式不存在"
                variable.pass_list.append('pass')
                write_var({'pass_list': variable.pass_list})
                INFO.logger.info(f"接口断言通过::{api_info}")
            else:
                WARNING.logger.warning(f"接口没有断言::{api_info}")
        except Exception as e:
            variable.fail_list.append('fail')
            write_var({'fail_list': variable.fail_list})
            ERROR.logger.error(f"{e}\n,详细错误信息{traceback.format_exc()}")
            raise e
if __name__ == '__main__':
    ast = AssertUtils()
    sql = ast.execute_sql("SELECT * from user_info where nickname = 'Ljiang5';",)
    print(sql)
    pass
